/*
 * HTMLArbre.cpp
 *
 *  Created on: 19 mars 2012
 *      Author: lsinapayen
 */

//TDOD fonction d'ajout à un html selon type ??

#include "HTMLArbre.h"

XMLArbre * myXsl;
vector<Item*> racineIts;

//si le template correspondant à nom existe dans l'xsl, renvoie vrai et le template
//sinon renvoie faux
pair <bool,ContentElement *> HTMLArbre::findTemplate(string * nom){
	vector<Item*>::iterator itItem;
	vector<Item*> * xslItems;
	vector<Attribut*>::iterator itAtt;
	Element * e;
	pair <bool,ContentElement *> retour;

	xslItems = myXsl->getRacine()->getItems();
	//parcourir les items de xsl 
	itItem = xslItems->begin();
	while(itItem != xslItems->end()){
		//si l'item est un élément parcourir ses attributs
		e = dynamic_cast<Element*>(*itItem);
		if (e){
			itAtt = e->getAttributs()->begin();
			while(itAtt != e->getAttributs()->end()){
				if(strcmp((*itAtt)->getVal()->c_str(),nom->c_str())==0){
					//template trouve, retour de la fonction
					retour.second = dynamic_cast<ContentElement*>(*itItem);
					if(retour.second){
						retour.first = true;
						return retour;
					}
					else {
						retour.first = false;
						return retour;
					}
				}
				else{
					//printf("html:- at:- attribut non trouvé \n");
				}
				itAtt++;
			}
		}
		else //printf("html:- at:- not element \n");
		itItem++;
	}
	retour.first = false;
	return retour;
}

//verifier si un élément vide est de type value-of
pair<bool,vector<Item*>* > HTMLArbre::IsValueof(EmptyElement * ee, ContentElement * e, vector<Item*>* items){
	vector<Attribut*>::iterator itAtt;
	vector<Item*>::iterator itE;
	pair<bool,vector<Item*>* > retour;

	string searchName;
	if(*(ee->getNomspace()) != "")
	{
		searchName = *(ee->getNomspace()) + ":" + *(ee->getName());
	}
	else
	{
		searchName = *(ee->getName());
	}
	if(strcmp(searchName.c_str(),"xsl:value-of")==0){
	//l'élément est bien un "value-of", rechercher la valeur de l'attribut select
		itAtt = ee->getAttributs()->begin();
		while(itAtt != ee->getAttributs()->end()){
			if(strcmp((*itAtt)->getName()->c_str(),"select")==0){ 
				//select trouvé, recherche de la valeur correspondante dans l'élement de l'arbre xml
				itE = e->getItems()->begin();
				while(itE!=e->getItems()->end()){

					if(strcmp((*itE)->getName()->c_str(),(*itAtt)->getVal()->c_str())==0){

						//element trouvé, copie
						vector<Item*>::iterator itE2;
						itE2 = ((Element *)(*itE))->getItems()->begin();
						while(itE2 != ((Element *)(*itE))->getItems()->end()){
							items->push_back(*itE2);
							itE2++;
						}
						retour.second = items;
						retour.first = true;
						return retour;
					}
					itE++;
				}
			}
			itAtt++;
		}
	}
	else{
	retour.first = false;
	}

	return retour;
}

//appliquer le template temp à l'element e et empiler dans items
void HTMLArbre::applyTemplate(Element * e, ContentElement * temp, vector<Item*> * items){
	vector<Item*>::iterator itTemp;
	vector<Item*>::iterator itE;
	Data * d;
	EmptyElement * ee;
	ContentElement * ce;

	//parcourir template
	itTemp = temp->getItems()->begin();
	while(itTemp!= temp->getItems()->end()){

		d = dynamic_cast<Data *>(*itTemp);
		//if data then push without change
		if(d){

			items->push_back(d);
		}
			//if "value of" element then look for value
			ee = dynamic_cast<EmptyElement *>(*itTemp);
			//recontre du'n noeud vide
			if(ee){
				pair<bool,vector<Item*>* > retour;
				//si le noeud est un apply-template ou un value of continuer le traitement...
				string searchName;
				if(*(ee->getNomspace()) != "")
				{
					searchName = *(ee->getNomspace()) + ":" + *(ee->getName());
				}
				else
				{
					searchName = *(ee->getName());
				}
				if(strcmp(searchName.c_str(),"xsl:apply-templates")==0){
					retour.first = true;
				}else
				retour = IsValueof(ee,(ContentElement*)e, items);
				if(!retour.first){
					//sinon empiler sans traiter
					items->push_back(ee);
				}
			}
			//if element is content element apply template to child dependig on its type
			ce = dynamic_cast<ContentElement *>(*itTemp);
			if(ce){

				if(ce->getItems()->size()==0){
					items->push_back(ce);

				}
				else{
					vector<Item*>::iterator itE2;

					ContentElement * ce2 = new ContentElement(ce->getName(), ce->getNomspace());
					vector<Item*> recursItems;

					itE2 = temp->getItems()->begin();
					while(itE2!=temp->getItems()->end()){
						Data * d2;

							EmptyElement * ee2;
							ee2 = dynamic_cast<EmptyElement *>(*itE2);
							if(ee2){
							//si élément vide vérifier sa nature comme précédemment
								pair<bool,vector<Item*>* > retour;
								retour.second = items;
								string searchName;
								if(*(ee2->getNomspace()) != "")
								{
									searchName = *(ee2->getNomspace()) + ":" + *(ee2->getName());
								}
								else
								{
									searchName = *(ee2->getName());
								}
								if((strcmp(searchName.c_str(),"xsl:apply-templates")==0)||(strcmp(searchName.c_str(),"xsl:value-of")==0)){

									retour.first = true;
								}
								if(!retour.first){
									items->push_back(ee2);

								}
							}
							else{
								d2 = dynamic_cast<Data *>(*itE2);
								EmptyElement * ee2 = dynamic_cast<EmptyElement*>(*itE2);
								//si data empiler tel quel
								if((!d2)&&(!ee2)){
								//sinon appel récursif sur ce fils
								applyTemplate(e, (ContentElement *)(*itE2),&recursItems);
								}
							}
						itE2++;
					}
					ce2->setItems(&recursItems);
					items->push_back(ce2);
				}
			}
		itTemp++;
	}
}



//parcourt les items d'un element et update racineIts en conséquence
//a appeler sur les items de racine ou directement sur racine
void HTMLArbre::parcoursItem(Item * i){
	Data * data;
	Element * e;
	vector<Item*>::iterator itItem;
	pair <bool,ContentElement *> foundTemplate;

	//si data alors empiler
	data = dynamic_cast<Data*>(i);
	if(data){
		racineIts.push_back(data);
		return;
	}

	//si element, chercher template
	e = dynamic_cast<Element*>(i);
	if(e){
		//si template existe, l'appliquer
		foundTemplate =findTemplate(e->getName());
		if (foundTemplate.first){
			bool apply = false;
			//faut it appliquer un template ?
			itItem = foundTemplate.second->getItems()->begin();
			apply = false;
			string searchName;
			while(itItem!= foundTemplate.second->getItems()->end()){
				if(*(*itItem)->getNomspace() != "")
				{
					searchName = *(*itItem)->getNomspace() + ":" + *(*itItem)->getName();
				}
				else
				{
					searchName = *(*itItem)->getName();
				}
				if(strcmp(searchName.c_str(),"xsl:apply-templates") == 0){
					apply = true;
				}
				itItem ++;
			}
			//appliquer template
			if(apply){
				applyTemplate(e,foundTemplate.second, &racineIts);
			}

		}
		//sinon rappeler la fonction sur les items de l'element
		else{

			itItem = e->getItems()->begin();
			while(itItem != e->getItems()->end()){

				parcoursItem(*itItem);
				itItem++;
			}
		}
	}
}

//constructeur
HTMLArbre::HTMLArbre(XMLArbre * xsl, XMLArbre * xml) : XMLArbre("root") {
	string xmlName;
	vector<Item*>::iterator itItem;
	vector<Item*> * xmlItems;
	vector<Item*> racineItems;

	myXsl = xsl;

	xmlItems = xml->getRacine()->getItems();
	itItem = xmlItems->begin();

	//appeler la fonction de parcours sur tous les items de la racinne de xml
	while(itItem != xmlItems->end()){
		parcoursItem(*itItem);
		itItem++;
	}

	this->racine->setItems(&racineIts); 

}

HTMLArbre::~HTMLArbre() {
	// TODO Auto-generated destructor stub
}
